package top.goldenyear.porpoise.framework.web.core.generator;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
import top.goldenyear.porpoise.framework.web.core.generator.config.GlobalConfig;
import top.goldenyear.porpoise.framework.web.core.generator.dialect.IDialect;
import top.goldenyear.porpoise.framework.web.core.generator.model.TableMeta;

/**
 * @author airhead
 */
@Slf4j
public class MetaBuilder implements IMetaBuilder {
  protected DataSource dataSource;
  protected IDialect dialect = IDialect.MYSQL;
  protected GlobalConfig globalConfig;
  protected Connection conn = null;
  protected DatabaseMetaData dbMeta = null;

  public MetaBuilder(DataSource dataSource, GlobalConfig globalConfig) {
    this.dataSource = dataSource;
    this.globalConfig = globalConfig;
  }

  public MetaBuilder(DataSource dataSource, GlobalConfig globalConfig, IDialect dialect) {
    this.dataSource = dataSource;
    this.globalConfig = globalConfig;
    this.dialect = dialect;
  }

  @Override
  public List<TableMeta> buildTables() {
    try {
      if (conn == null) {
        conn = dataSource.getConnection();
        dbMeta = conn.getMetaData();
      }

      String schemaName = globalConfig.getStrategyConfig().getGenerateSchema();
      List<TableMeta> tableMetas = new ArrayList<>();
      try (ResultSet rs = getTablesResultSet(schemaName)) {
        while (rs.next()) {
          String tableName = rs.getString("TABLE_NAME");
          if (!globalConfig.getStrategyConfig().isSupportGenerate(tableName)) {
            continue;
          }

          TableMeta tableMeta = new TableMeta();
          tableMeta.setSchema(schemaName);
          tableMeta.setName(tableName);
          String remarks = rs.getString("REMARKS");
          tableMeta.setComment(remarks);
          buildPrimaryKey(tableMeta);

          dialect.buildTableColumns(tableMeta, dbMeta, conn);

          tableMetas.add(tableMeta);
        }
      }
      return tableMetas;
    } catch (SQLException e) {
      log.error("构建表信息错误", e);

      return new ArrayList<>();
    }
  }

  protected ResultSet getTablesResultSet(String schema) throws SQLException {
    if (globalConfig.getStrategyConfig().isGenerateForView()) {
      return dialect.getTablesResultSet(dbMeta, conn, schema, new String[] {"TABLE", "VIEW"});
    } else {
      return dialect.getTablesResultSet(dbMeta, conn, schema, new String[] {"TABLE"});
    }
  }

  protected void buildPrimaryKey(TableMeta tableMeta) throws SQLException {
    try (ResultSet rs = dbMeta.getPrimaryKeys(conn.getCatalog(), null, tableMeta.getName())) {
      while (rs.next()) {
        String primaryKey = rs.getString("COLUMN_NAME");
        tableMeta.addPrimaryKey(primaryKey);
      }
    }
  }
}
